import {
  addEdge,
  Background,
  BaseEdge,
  getBezierPath,
  Handle,
  Position,
  ReactFlow,
  ReactFlowProvider,
  useEdgesState,
  useNodesState
} from '@xyflow/react';
import { useCallback, useMemo, useState } from 'react';
// 引入 React Flow 的 CSS 样式
import '@xyflow/react/dist/style.css';

// 连线自定义样式
function CustomEdge({ id, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, markerEnd }) {
  // const { setEdges } = useReactFlow();

  // 使用库提供的 getBezierPath 函数计算出 SVG 路径
  const [edgePath, labelX, labelY] = getBezierPath({
    sourceX,
    sourceY,
    sourcePosition,
    targetX,
    targetY,
    targetPosition,
  });

  // // 2. 在按钮点击时，从 edges 状态中移除自己
  // const onEdgeClick = () => {
  //   setEdges((edges) => edges.filter((edge) => edge.id !== id));
  // };

  return (
    <>
      {/* 默认的 SVG 路径 */}
      <BaseEdge path={edgePath} markerEnd={markerEnd} style={{
        strokeWidth: 2,
        stroke: '#595959',
        strokeDasharray: '5 5', // <-- 关键属性：设置虚线
      }} />

      {/* 使用 foreignObject 在 SVG 路径上渲染 HTML 元素 (例如按钮) */}
      <foreignObject
        width={32}
        height={24}
        x={labelX - 16} // 将按钮定位在线条中心
        y={labelY - 12}
        className="edgebutton-foreignobject"
        requiredExtensions="http://www.w3.org/1999/xhtml"
      >
        <div style={{
          width: '32px',
          height: '24px',
          background: '#FFFFFF',
          border: '1px dashed #387EE8',
          display: 'flex',
          justifyContent: 'center',
          alignItems: 'center',
        }}>111</div>
      </foreignObject>
    </>
  );
}

// 注册自定义边类型
const edgeTypes = {
  custom: CustomEdge,
};

// 这是一个基础的自定义节点样式
const nodeStyles = {
  background: '#fff',
  border: '1px solid #1a192b',
  borderRadius: '3px',
  width: '120px',
  height: '40px',
  fontSize: '12px',
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'center',
};

function CustomNode({ data }) {
  return (
    <div style={nodeStyles}>
      {/* 左侧连接点 (目标)
        - type="target": 表示这条线只能连"入"这个点
        - position={Position.Left}: 将点放在节点的左侧边框中间
      */}
      {data.handle === 'left' && <Handle type="target" position={Position.Left} />}

      {/* 节点显示的内容 */}
      <div>{data.label}</div>

      {/* 右侧连接点 (源)
        - type="source": 表示这条线只能从这个点"连出"
        - position={Position.Right}: 将点放在节点的右侧边框中间
      */}
      {data.handle === 'right' && <Handle type="source" position={Position.Right} />}
    </div>
  );
}

function PlaceholderNode() {
  return (
    <div
      style={{
        background: 'transparent',
        border: '1px dashed #999',
        borderRadius: '3px',
        width: '120px',
        height: '40px',
        fontSize: '12px',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        color: '#888',
      }}
    >
      {/* 添加一个 Handle，这样新节点可以从左侧连接到它 */}
      <Handle type="target" position={Position.Left} style={{ opacity: 0 }} />
      拖拽至此进行关联
    </div>
  );
}

let id = 1; // 用于生成唯一ID
const getUniqueId = () => `dndnode_${id++}`;

// 定义自定义节点的类型映射
const nodeTypes = {
  placeholder: PlaceholderNode,
  custom: CustomNode,
};

// 侧边栏组件
const Sidebar = ({ onDragStart, onDragEnd }) => {
  const handleDragStart = (event, nodeType, label) => {
    event.dataTransfer.setData('application/reactflow-type', nodeType);
    event.dataTransfer.setData('application/reactflow-label', label);
    event.dataTransfer.effectAllowed = 'move';
    onDragStart(); // 通知父组件拖拽开始
  };

  return (
    <aside style={{ borderRight: '1px solid #eee', padding: '15px', fontSize: '12px' }}>
      <div className="description" style={{ marginBottom: '20px' }}>您可以将这些节点拖拽到右侧的画布中。</div>
      <div
        className="dndnode"
        onDragStart={(event) => handleDragStart(event, 'input', '条码信息')}
        onDragEnd={onDragEnd} // 通知父组件拖拽结束
        draggable
        style={{ padding: '10px', border: '1px solid #ddd', borderRadius: '5px', marginBottom: '10px', cursor: 'grab', backgroundColor: '#fff' }}
      >
        条码信息
      </div>
      <div
        className="dndnode input"
        onDragStart={(event) => handleDragStart(event, 'input', '唯一码生成信息')}
        onDragEnd={onDragEnd} // 通知父组件拖拽结束
        draggable
        style={{ padding: '10px', border: '1px solid #ddd', borderRadius: '5px', marginBottom: '10px', cursor: 'grab', backgroundColor: '#fff' }}
      >
        唯一码生成信息
      </div>
      <div
        className="dndnode output"
        onDragStart={(event) => handleDragStart(event, 'input', '条码配置')}
        onDragEnd={onDragEnd} // 通知父组件拖拽结束
        draggable
        style={{ padding: '10px', border: '1px solid #ddd', borderRadius: '5px', cursor: 'grab', backgroundColor: '#fff' }}
      >
        条码配置
      </div>
    </aside>
  );
};


const Flow = () => {
  const [nodes, setNodes, onNodesChange] = useNodesState([]);
  const [edges, setEdges, onEdgesChange] = useEdgesState([]);

  // 1. 追踪拖拽状态
  const [isDragging, setIsDragging] = useState(false);

  const onConnect = useCallback((params) => setEdges((eds) => addEdge(params, eds)), [setEdges]);

  function onDragStart() {
    // setIsDragging(true);
    // setNodes((nds) => {
    //   const placeholderNodes = []
    //   for (let i = 0; i < nds.length; i++) {
    //     const node = nds[i];
    //     const placeholderPosition = {
    //       x: node.position.x + (node.width || 100) + 50, // 在原节点右侧生成
    //       y: node.position.y,
    //     };
    //     placeholderNodes.push({
    //       id: `placeholder-for-${node.id}`,
    //       type: 'placeholder',
    //       position: placeholderPosition,
    //       data: { sourceNodeId: node.id }, // 存储源节点ID
    //       draggable: false,
    //     })
    //   }
    //   return [...nds, ...placeholderNodes]
    // })
  }

  function onDragEnd(event) {
    setIsDragging(false)
    console.log(event);
  }

  const handleDragEnter = (event) => {
    // 防止子元素触发重复的 enter/leave 事件
    if (event.currentTarget.contains(event.relatedTarget)) {
      return;
    }
    console.log('Drag Enter Canvas');
    setIsDragging(true);

    setNodes((nds) => {
      const placeholderNodes = []
      if (nds.length > 0) {
        for (let i = 0; i < nds.length; i++) {
          const node = nds[i];
          const placeholderPosition = {
            x: node.position.x + (node.width || 100) + 150, // 在原节点右侧生成
            y: node.position.y,
          };
          placeholderNodes.push({
            id: `placeholder-for-${node.id}`,
            type: 'placeholder',
            position: placeholderPosition,
            data: { sourceNodeId: node.id }, // 存储源节点ID
            draggable: false,
          })
        }
      } else {
        placeholderNodes.push({
          id: `placeholder-for-1`,
          type: 'placeholder',
          position: { x: 10, y: 20 },
          data: { sourceNodeId: 1 }, // 存储源节点ID
          draggable: false,
        })
      }

      return [...nds, ...placeholderNodes]
    })
  };

  const handleDragLeave = (event) => {
    if (event.currentTarget.contains(event.relatedTarget)) {
      return;
    }
    console.log('Drag Leave Canvas');
    setIsDragging(false);
    setNodes((nds) => nds.filter(node => node.type !== 'placeholder'));
  };

  // 2. 根据 isDragging 动态生成占位符节点
  // const placeholderNodes = useMemo(() => {
  //   if (!isDragging) return [];

  //   // 为每个非占位符的常规节点创建一个占位符
  //   return nodes
  //     .filter((node) => node.type !== 'placeholder')
  //     .map((node) => {
  //       const placeholderPosition = {
  //         x: node.position.x + (node.width || 100) + 50, // 在原节点右侧生成
  //         y: node.position.y,
  //       };
  //       return {
  //         id: `placeholder-for-${node.id}`,
  //         type: 'placeholder',
  //         position: placeholderPosition,
  //         data: { sourceNodeId: node.id }, // 存储源节点ID
  //         draggable: false,
  //       };
  //     });
  // }, [nodes, isDragging]);

  // 合并常规节点和占位符节点用于渲染
  const allNodes = useMemo(() => [...nodes], [nodes]);



  // 处理拖拽到画布上的事件
  const onDragOver = useCallback((event) => {
    event.preventDefault(); // 必须调用，否则 onDrop 不会触发
    event.dataTransfer.dropEffect = 'move';
  }, []);

  // 一个计算两点距离的辅助函数
  // const getDistance = (pos1, pos2) => {
  //   return Math.sqrt(Math.pow(pos1.x - pos2.x, 2) + Math.pow(pos1.y - pos2.y, 2));
  // };

  // **修正点 1: 使用统一的 onDrop 事件处理器**
  const onDrop = useCallback(
    (event) => {
      event.preventDefault();
      setIsDragging(false);

      const type = event.dataTransfer.getData('application/reactflow-type');
      if (!type) {
        return;
      }
      const label = event.dataTransfer.getData('application/reactflow-label');

      // **修正点 2: 判断放置目标是节点还是画布**
      const target = event.target;
      const targetIsNode = target.closest('.react-flow__node');
      if (targetIsNode) {
        // --- 逻辑分支 1: 放置在节点上 ---
        const targetNodeId = targetIsNode.dataset.id;
        const targetNode = allNodes.find(node => node.id === targetNodeId);

        // 只处理在占位符上放置的情况
        if (targetNode && targetNode.type === 'placeholder') {
          const { sourceNodeId } = targetNode.data;
          const newNodeId = getUniqueId();
          const newNode = {
            id: newNodeId,
            type: 'custom', // **修正点 4: 使用从侧边栏传递过来的 type**
            position: targetNode.position,
            data: { label, handle: nodes.filter(node => node.type !== 'placeholder').length === 0 ? 'right' : 'left' },
            draggable: false
          };

          const newEdge = {
            id: `edge-${sourceNodeId}-${newNodeId}`,
            source: sourceNodeId,
            target: newNodeId,
            type: 'custom',
          };
          // **修正点 3: 在操作开始时就重置拖拽状态，确保占位符消失**
          setNodes((nds) => nds.concat(newNode).filter(node => node.type !== 'placeholder'));
          setEdges((eds) => eds.concat(newEdge));
        }
      } else {
        setNodes((nds) => nds.filter(node => node.type !== 'placeholder'));
      }
    },
    [allNodes, setEdges, setNodes]
  );

  const onNodeClick = useCallback((event, node) => {
    // node 对象包含了该节点的所有信息：id, data, position 等
    console.log('点击了节点:', node);

    // 您可以在这里执行任何操作，比如弹窗或更新状态
    // alert(`你点击了节点 "${node.data.label}" (ID: ${node.id})`);

    // 例如，可以将选中的节点ID存入 state，用于在别处显示详情
    // setSelectedNodeId(node.id);

  }, []);

  return (
    <div className="dndflow" style={{ display: 'flex', height: '100vh', flexDirection: 'row' }}>
      <Sidebar
        onDragStart={onDragStart}
        onDragEnd={onDragEnd}
      />
      <div className="reactflow-wrapper" style={{ flexGrow: 1 }} onDragEnter={handleDragEnter}
        onDragLeave={handleDragLeave}
        onDragOver={onDragOver} // onDragOver 也可放在这里，确保整个区域可放置
      >
        <ReactFlow
          nodes={allNodes}
          edges={edges}
          onNodeClick={onNodeClick}
          onNodesChange={onNodesChange}
          onEdgesChange={onEdgesChange}
          onConnect={onConnect}
          onDragOver={onDragOver}
          onDrop={onDrop} // **修正点 1: 使用统一的 onDrop**
          nodeTypes={nodeTypes} // 注册自定义节点类型
          // fitView
          edgeTypes={edgeTypes}
          panOnDrag={false}
          zoomOnScroll={false}
          zoomOnPinch={false}
          zoomOnDoubleClick={false}
        // nodesDraggable={false}
        >
          {/* <Controls /> */}
          <Background />
        </ReactFlow>
      </div>
    </div>
  );
};

// 我们需要使用 ReactFlowProvider 包裹 Flow 组件，以便 useReactFlow hook 能够正常工作
export default function DragAndDropFlow() {
  return (
    <ReactFlowProvider>
      <Flow />
    </ReactFlowProvider>
  );
}
